using System;
using System.Collections.Generic;
using System.Text;
using DSP.MathLibrary;
using System.Collections;

namespace DSP.Library
{
    public class SignalProcessing
    {
        public SignalProcessing()
        {

        }

        public static ArrayList CountAutoCorrelation(ArrayList inArr)
        {
            ArrayList arr = new ArrayList();
            ComplexNumber avg = Average(inArr);
            int count = inArr.Count;
            int m_max = count;
            int m_min = -count - 1;

            for (int m = 0; m < m_max; m++)
            {
                double re = 0;
                for (int i = 0; i < count - m - 1; i++)
                {
                    re += (((ComplexNumber)inArr[i]).Re - avg.Re) * (((ComplexNumber)inArr[i + m]).Re - avg.Re);
                }
                arr.Add(new ComplexNumber(re, 0));
            }
            //arr.InsertRange(0, arr);
            return arr;

        }

        public static ArrayList CountAutoCorrelation(ArrayList inArr1, ArrayList inArr2)
        {
            ArrayList arr = new ArrayList();
            ComplexNumber avg1 = Average(inArr1);
            ComplexNumber avg2 = Average(inArr2);
            int count1 = inArr2.Count;
            int m_max1 = count1;

            for (int m = 0; m < m_max1; m++)
            {
                double re = 0;
                for (int i = 0; i < count1 - m - 1; i++)
                {
                    re += (((ComplexNumber)inArr1[i]).Re - avg1.Re) * (((ComplexNumber)inArr2[i + m]).Re - avg2.Re);
                }
                arr.Add(new ComplexNumber(re, 0));
            }
            //arr.InsertRange(0, arr);
            return arr;

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="inArr"></param>
        /// <returns></returns>
        public static ArrayList CountSPM(ArrayList inArr)
        {
            return FourierTransform.CountSPM(inArr);
        }

        public static ArrayList CountSPMS(ArrayList inArr, int windowWidth)
        {
            ArrayList arr = new ArrayList();
            ArrayList spm = CountSPM(inArr);
            for (int i = 0; i < inArr.Count - windowWidth; i++)
            {
                if (i < windowWidth)
                {
                    arr.Add(new ComplexNumber(0, 0));
                }
                else
                {
                    ComplexNumber tmp = new ComplexNumber(0, 0);
                    for (int j = -windowWidth; j < windowWidth; j++)
                    {
                        tmp += (ComplexNumber)spm[i - j];
                    }
                    arr.Add(new ComplexNumber(tmp.Re / (2 * windowWidth + 1), tmp.Im));
                }
            }
            return arr;
        }

        public static ArrayList CountSPMS(ArrayList inArr1, ArrayList inArr2, int windowWidth)
        {
            ArrayList arr = new ArrayList();
            ArrayList cor = CountAutoCorrelation(inArr1, inArr2);
            ArrayList spm = FourierTransform.CountFastFourierTransform(cor, true);
            for (int i = 0; i < inArr1.Count - windowWidth; i++)
            {
                if (i < windowWidth)
                {
                    arr.Add(new ComplexNumber(0, 0));
                }
                else
                {
                    ComplexNumber tmp = new ComplexNumber(0, 0);
                    for (int j = -windowWidth; j < windowWidth; j++)
                    {
                        tmp += (ComplexNumber)spm[i - j];
                    }
                    arr.Add(new ComplexNumber(tmp.Re / (2 * windowWidth + 1), tmp.Im));
                }
            }
            return arr;
        }

        public static ArrayList CountAutoCorrelationFromSPM(ArrayList inArr)
        {
            return FourierTransform.CountFastFourierTransform(FourierTransform.CountSPM(inArr), true);
        }

        public static ArrayList CountAutoCorrelationByFFT(ArrayList inArr1, ArrayList inArr2)
        {
            ArrayList arr = new ArrayList();
            ArrayList fft1 = new ArrayList();
            ArrayList fft2 = new ArrayList();
            ArrayList tmp = new ArrayList();
            ArrayList fft3 = new ArrayList();

            ComplexNumber avg1 = Average(inArr1);
            ComplexNumber avg2 = Average(inArr2);

            for (int i = 0; i < inArr1.Count; i++)
            {
                inArr1[i] = (ComplexNumber)inArr1[i] - avg1;
            }
            for (int i = 0; i < inArr2.Count; i++)
            {
                inArr2[i] = (ComplexNumber)inArr2[i] - avg2;
            }

            fft1 = FourierTransform.CountFastFourierTransform(inArr1, false);
            fft2 = FourierTransform.CountFastFourierTransform(inArr2, false);

            for (int i = 0; i < inArr1.Count; i++)
            {
                ComplexNumber cn1 = (ComplexNumber)fft1[i];
                ComplexNumber cn2 = ComplexNumber.inv((ComplexNumber)fft2[i]);
                tmp.Add(cn1 * cn2);
            }

            fft3 = FourierTransform.CountFastFourierTransform(tmp, true);

            for (int i = 0; i < fft3.Count; i++)
            {
                arr.Add(fft3[i]);
            }
            return arr;
        }

        public static ComplexNumber Average(ArrayList arr)
        {
            ComplexNumber cn = new ComplexNumber(0, 0);
            int count = arr.Count;
            foreach (ComplexNumber tmp in arr)
            {
                cn += new ComplexNumber(tmp.Re / count, tmp.Im / count);
            }
            return cn;
        }

        public static ArrayList CountCogerent(ArrayList inArr1, ArrayList inArr2, int windowWidth)
        {
            ArrayList arr = new ArrayList();
            ArrayList gxy = new ArrayList();
            ArrayList gx = new ArrayList();
            ArrayList gy = new ArrayList();



            gxy = CountSPMS(inArr1, inArr2, windowWidth);
            gx = CountSPMS(inArr1, windowWidth);
            gy = CountSPMS(inArr2, windowWidth);

            for (int i = 0; i < gxy.Count; i++)
            {
                double gxyk = ((ComplexNumber)gxy[i]).Re;
                double gxk = ((ComplexNumber)gx[i]).Re;
                if (gxk == 0) gxk = 1;
                double gyk = ((ComplexNumber)gy[i]).Re;
                if (gyk == 0) gyk = 1;
                arr.Add(new ComplexNumber(gxyk / (gxk * gyk), 0));
            }


            return arr;
        }

        public static ArrayList CountAFC(ArrayList inArr1, ArrayList inArr2, int windowWidth)
        {
            ArrayList arr = new ArrayList();
            ArrayList gxy = new ArrayList();
            ArrayList gx = new ArrayList();



            gxy = CountSPMS(inArr1, inArr2, windowWidth);
            gx = CountSPMS(inArr1, windowWidth);


            for (int i = 0; i < gxy.Count; i++)
            {
                double gxyk = ((ComplexNumber)gxy[i]).Mod;
                double gxk = ((ComplexNumber)gx[i]).Re;
                if (gxk == 0) gxk = 1;

                arr.Add(new ComplexNumber(gxyk / gxk, 0));
            }


            return arr;
        }

    }

}
